Nginx + OAuth2 Proxy + StreamlitでGoogleログイン後にStreamlitにアクセスする環境をローカルコンテナ環境で作ってみた
こんちには。
データアナリティクス事業本部 機械学習チームの中村(nokomoro3)です。
今回は、Nginx + OAuth2 Proxy + StreamlitでGoogleログイン後にStreamlitにアクセスする環境をローカルコンテナ環境で作ってみます。
実行環境と準備
実行環境としてはWindows 10マシンを使います。
また前提としてRancher Desktopをセットアップ済みであり、Googleの認証情報作成のためにGoogle Cloudにログインできる環境を作成済みという前提で進めます。
Rancher Desktopのセットアップについては以下も参考にされてください。
Streamlitのコンテナ作成
まずはStreamlit単体のコンテナを作成します。
Dockerfileの作成
以下のようなDockerfileを./streamlit/Dockerfile
に作成しました。
FROM python:3.9-slim WORKDIR /app RUN apt-get update && apt-get install -y \ build-essential \ curl \ software-properties-common \ git \ && rm -rf /var/lib/apt/lists/* RUN git clone https://github.com/streamlit/streamlit-example.git . RUN pip3 install -r requirements.txt EXPOSE 8501 HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health ENTRYPOINT ["streamlit", "run", "streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
以下の公式ドキュメントを参考に作成しています。
docker-compose.ymlの作成
こちらをdocker-composeで立ち上げるために、./docker-compose.yml
を作成します。
version: '3' services: streamlit: container_name: streamlit build: context: ./streamlit dockerfile: Dockerfile ports: - 8501:8501
動作確認
docker-composeを使って起動します。
docker compose up -d
localhost:8501
にアクセスすると、以下のような画面を確認できます。
Nginxのリバースプロキシを追加
次にNginxにアクセス後、Streamlitに転送されるような構成をしていきます。
nginx.confの作成
まずは./nginx/nginx.conf
を以下のように記載します。
events { worker_connections 16; } http { server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } location /streamlit/ { proxy_pass http://streamlit:8501/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } }
何も考えずにproxy_pass
のみの設定を記載すると、WebSocket関連でエラーが出たので以下を参考に設定をしています。
docker-compose.ymlの追記
./docker-compose.yml
にNginxの部分を追記します。
nginx: container_name: nginx image: nginx:latest volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf ports: - 8000:80 depends_on: - streamlit
動作確認
再度立ち上げなおします。
docker-compose down docker-compose up -d
localhost:8000/streamlit
にアクセスすると、先ほどと同じStreamlitの画面を確認できるはずです。
OAuth2 Proxyの導入
OAuth 同意画面の作成
以下に従って、OAuth Providerの設定を行っていきます。
まずは以下にアクセスし使用するプロジェクトを選択します。
- https://console.cloud.google.com
以下のメニューで、「OAuth 同意画面」を作成します。(なお「OAuth 同意画面」はプロジェクトに対して一つ作成する形になりますので、既に存在する場合は流用などをされてください)
User Typeを「内部」とすることで、Google Cloudのプロジェクトと同じ組織内のGoogleアカウントがログインできるようになります。
アプリ名を適当に入力し、メールアドレスを入力します。
デベロッパーの連絡先としてメールアドレスをこちらにも入力します。
以降は特に変更せず進めて「OAuth 同意画面」の作成は完了です。
認証情報の作成
「認証情報」を作成していきます。
「認証情報を作成」を押下し、「OAuth クライアント ID」をクリックします。
「ウェブ アプリケーション」を選択し、適当な名前を入力して押下します。
承認済みのリダイレクトURIに以下を追記して、「作成」を押下します。
こちらのリダイレクトURIは、後程OAuth2 Proxyの設定で使用します。
最後にクライアントIDとクライアントシークレットが表示されますので、控えておきます。
以上で認証情報の設定は完了です。
docker-compose.ymlの追記
docker-compose.yml
にOAuth2 Proxyのコンテナを追加していきます。
oauth2-proxy: container_name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:latest ports: - "4180:4180" env_file: - ./oauth2_proxy.env
また、./oauth2_proxy.env
は以下のようにOAuth2 Proxyの設定値を記載しておきます。
OAUTH2_PROXY_PROVIDER=google OAUTH2_PROXY_CLIENT_ID={作成したクライアントID} OAUTH2_PROXY_CLIENT_SECRET={作成したクライアントシークレット} OAUTH2_PROXY_COOKIE_SECRET={パスワードジェネレータなどで作成するランダムな文字列} OAUTH2_PROXY_REDIRECT_URL={認証情報作成時に記載した承認済みリダイレクトURI} OAUTH2_PROXY_EMAIL_DOMAINS="*" OAUTH2_PROXY_HTTP_ADDRESS="0.0.0.0:4180" OAUTH2_PROXY_COOKIE_SECURE=false
OAUTH2_PROXY_COOKIE_SECRETは自身でパスワードジェネレータなどを使って、ランダムな文字列を作成してください。
nginx.confの修正
最後にNginxからOAuth2 Proxyに転送するよう./nginx/nginx.conf
に設定を追加します。
events { worker_connections 16; } http { server { listen 80; server_name localhost; location / { auth_request /oauth2/auth; error_page 401 = /oauth2/sign_in; root /usr/share/nginx/html; index index.html index.htm; } location /streamlit/ { auth_request /oauth2/auth; error_page 401 = /oauth2/sign_in; proxy_pass http://streamlit:8501/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location = /oauth2/callback { proxy_pass http://oauth2-proxy:4180; } location /oauth2/ { proxy_pass http://oauth2-proxy:4180; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_set_header X-Auth-Request-Redirect $request_uri; } location = /oauth2/auth { proxy_pass http://oauth2-proxy:4180; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_set_header Content-Length ""; proxy_pass_request_body off; } } }
動作確認
再度立ち上げなおします。
docker-compose down docker-compose up -d
localhost:8000/streamlit
にアクセスすると、以下のようにOAuth2 Proxyの画面に遷移します。
OAuth 同意画面が表示されますので、アカウントを選択して進みます。
「次へ」を押下して進みます。
すると、streamlitの画面に転送されます。
Nginx側(localhost:8000
)にも認証が必要となるよう設定をしましたが、一度Streamlit側で認証済みであればこちらにもアクセスできるようになります。
補足
最終なdocker-compose.ymlの記載
最終的にはStreamlitもOAuth2 ProxyもNginx経由でアクセスするので、ポートの設定を削除してもOKです。
version: '3' services: streamlit: container_name: streamlit build: context: ./streamlit dockerfile: Dockerfile nginx: container_name: nginx image: nginx:latest volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf ports: - 8000:80 depends_on: - streamlit - oauth2-proxy oauth2-proxy: container_name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:latest env_file: - ./oauth2_proxy.env
ログインをやり直して動作確認するには
ブラウザの開発ツールのApplicationタブで、StorageのCookiesにhttp://localhost:8000があると思いますので、そちらをClearすれば再度ログインからやり直して動作確認できます。
まとめ
いかがでしたでしょうか。GoogleをIdPとしたログインは組織内部に限定することも可能ですので、社内に限定公開したい場合などに有効に使えそうです。
これらをAWS上にデプロイする方法も今後記事にしたいと思います。本記事が皆様のご参考になれば幸いです。